{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c478ebb2",
   "metadata": {},
   "source": [
    "(mlflow-tracker)=\n",
    "# MLflow tracker\n",
    "\n",
    "This tutorial demonstrates how to seamlessly integrate and transfer logs from MLflow to MLRun, creating a unified and powerful platform for your machine learning experiments.\n",
    "\n",
    "You can combine MLflow and MLRun for a comprehensive solution for managing, tracking, and deploying machine learning models. \n",
    "\n",
    "This notebook guides you through the process of:\n",
    "\n",
    "1. Setting up the integration between MLflow and MLRun.\n",
    "2. Extracting data, metrics, and artifacts from MLflow experiments.\n",
    "3. Creating MLRun artifacts and projects to organize and manage the transferred data.\n",
    "4. Leveraging MLRun's capabilities for model deployment and data processing.\n",
    "\n",
    "By the end of this tutorial, you will have a understanding of how to establish a smooth flow of data between MLflow and MLRun.\n",
    "\n",
    "**In this tutorial**\n",
    "- [MLRun installation and configuration](#mlrun-installation-and-configuration)\n",
    "- [Create an MLflow Xgboost function](#create-an-mlflow-xgboost-function)\n",
    "- [Log the data from MLflow in MLRun](#log-the-data-from-mlflow-in-mlrun)\n",
    "- [Use the function for model serving](#use-the-function-for-model-serving)\n",
    "\n",
    "## MLRun installation and configuration\n",
    "Before running this notebook make sure the mlrun package is installed (pip install mlrun) and that you have configured the access to MLRun service."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ab49e1f1",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Install MLRun and scikit-learn if not already installed. Run this only once. Restart the notebook after the install!\n",
    "%pip install mlrun scikit-learn~=1.5.2 xgboost~=2.0.3 mlflow~=2.16"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9a8db175-51f4-4218-afd1-752cc0e65216",
   "metadata": {
    "tags": []
   },
   "source": [
    "## Create an MLflow Xgboost function\n",
    "\n",
    " The `training.py` contains just mlflow code, and does not have any dependence on MLRun."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "44a1e133-954d-47a3-9b0f-6e181fe12ea7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting training.py\n"
     ]
    }
   ],
   "source": [
    "%%writefile training.py\n",
    "\n",
    "import mlflow\n",
    "import mlflow.xgboost\n",
    "import xgboost as xgb\n",
    "from mlflow import log_metric\n",
    "from sklearn import datasets\n",
    "from sklearn.metrics import accuracy_score, log_loss\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "def example_xgb_run():\n",
    "    # Prepare, train, and test data\n",
    "    iris = datasets.load_iris()\n",
    "    X = iris.data\n",
    "    y = iris.target\n",
    "    X_train, X_test, y_train, y_test = train_test_split(\n",
    "        X, y, test_size=0.2, random_state=42\n",
    "    )\n",
    "\n",
    "    # Enable auto logging\n",
    "    mlflow.xgboost.autolog()\n",
    "\n",
    "    dtrain = xgb.DMatrix(X_train, label=y_train)\n",
    "    dtest = xgb.DMatrix(X_test, label=y_test)\n",
    "\n",
    "    with mlflow.start_run():\n",
    "        # Train model\n",
    "        params = {\n",
    "            \"objective\": \"multi:softprob\",\n",
    "            \"num_class\": 3,\n",
    "            \"learning_rate\": 0.3,\n",
    "            \"eval_metric\": \"mlogloss\",\n",
    "            \"colsample_bytree\": 1.0,\n",
    "            \"subsample\": 1.0,\n",
    "            \"seed\": 42,\n",
    "        }\n",
    "        model = xgb.train(params, dtrain, evals=[(dtrain, \"train\")])\n",
    "        \n",
    "        # Evaluate model\n",
    "        y_proba = model.predict(dtest)\n",
    "        y_pred = y_proba.argmax(axis=1)\n",
    "        loss = log_loss(y_test, y_proba)\n",
    "        acc = accuracy_score(y_test, y_pred)\n",
    "        \n",
    "        # Log metrics by hand\n",
    "        mlflow.log_metrics({\"log_loss\": loss, \"accuracy\": acc})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1cf984c9-78a9-443f-9465-111263101dcd",
   "metadata": {},
   "source": [
    "## Log the data from MLflow in MLRun "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "365e4b39-9f39-40ae-aac4-7c4f42bce9bd",
   "metadata": {},
   "source": [
    "### Change the MLRun configuration to use the tracker"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "0b194d04-e08f-4161-a65b-4f18d10fdbf0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import mlrun\n",
    "\n",
    "mlrun.mlconf.external_platform_tracking.enabled = True"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b16bb4db-8a2a-4453-a42e-0e8e74ab8f53",
   "metadata": {},
   "source": [
    "To run the tracking, set:\n",
    "`mlrun.mlconf.external_platform_tracking.mlflow.match_experiment_to_runtime` to True.<br>\n",
    "This makes the MLRun run-id the same as the MLFlow experiment ID.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8b7bc72a-bd1b-408a-afa8-e474d91c4a20",
   "metadata": {},
   "source": [
    "### Create the project and function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "3382b909-a8dc-41a3-afb1-b64df9bb7318",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> 2025-09-12 04:28:06,900 [info] Project loaded successfully: {\"project_name\":\"mlflow-tracking-example\"}\n"
     ]
    }
   ],
   "source": [
    "# Set the tracking\n",
    "mlrun.mlconf.external_platform_tracking.mlflow.match_experiment_to_runtime = True\n",
    "\n",
    "# Create a project for this demo:\n",
    "project = mlrun.get_or_create_project(\n",
    "    name=\"mlflow-tracking-example\", context=\"./\", allow_cross_project=True\n",
    ")\n",
    "\n",
    "# Create a MLRun function using the example train file (all the functions must be located in it):\n",
    "training_func = project.set_function(\n",
    "    func=\"training.py\",\n",
    "    name=\"example-xgb-run\",\n",
    "    kind=\"job\",\n",
    "    image=\"mlrun/mlrun\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "91597f57-364d-4d2a-b926-97b9d8afc81b",
   "metadata": {},
   "source": [
    "### Run the function\n",
    "\n",
    "After running the function, you can look at the UI and see that all metrics and parameters are logged in MLRun."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "8ba452dd-1756-4bfb-af64-d741e234dba3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> 2025-09-11 16:51:38,489 [info] Storing function: {\"db\":\"http://mlrun-api:8080\",\"name\":\"example-xgb-run-example-xgb-run\",\"uid\":\"b45e8ffff4c34852b680d0a173b36297\"}\n",
      "[0]\ttrain-mlogloss:0.74723\n",
      "[1]\ttrain-mlogloss:0.54060\n",
      "[2]\ttrain-mlogloss:0.40276\n",
      "[3]\ttrain-mlogloss:0.30789\n",
      "[4]\ttrain-mlogloss:0.24051\n",
      "[5]\ttrain-mlogloss:0.19086\n",
      "[6]\ttrain-mlogloss:0.15471\n",
      "[7]\ttrain-mlogloss:0.12807\n",
      "[8]\ttrain-mlogloss:0.10722\n",
      "[9]\ttrain-mlogloss:0.09053\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2025/09/11 16:51:44 WARNING mlflow.utils.autologging_utils: MLflow autologging encountered a warning: \"/User/.pythonlibs/mlrun-base/lib/python3.9/site-packages/xgboost/core.py:160: UserWarning: [16:51:44] WARNING: /workspace/src/c_api/c_api.cc:1240: Saving into deprecated binary model format, please consider using `json` or `ubj`. Model format will default to JSON in XGBoost 2.2 if not specified.\"\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<style>\n",
       ".dictlist {\n",
       "  background-color: #4EC64B;\n",
       "  text-align: center;\n",
       "  margin: 4px;\n",
       "  border-radius: 3px; padding: 0px 3px 1px 3px; display: inline-block;}\n",
       ".artifact {\n",
       "  cursor: pointer;\n",
       "  background-color: #4EC64B;\n",
       "  text-align: left;\n",
       "  margin: 4px; border-radius: 3px; padding: 0px 3px 1px 3px; display: inline-block;\n",
       "}\n",
       "div.block.hidden {\n",
       "  display: none;\n",
       "}\n",
       ".clickable {\n",
       "  cursor: pointer;\n",
       "}\n",
       ".ellipsis {\n",
       "  display: inline-block;\n",
       "  max-width: 60px;\n",
       "  white-space: nowrap;\n",
       "  overflow: hidden;\n",
       "  text-overflow: ellipsis;\n",
       "}\n",
       ".master-wrapper {\n",
       "  display: flex;\n",
       "  flex-flow: row nowrap;\n",
       "  justify-content: flex-start;\n",
       "  align-items: stretch;\n",
       "}\n",
       ".master-tbl {\n",
       "  flex: 3\n",
       "}\n",
       ".master-wrapper > div {\n",
       "  margin: 4px;\n",
       "  padding: 10px;\n",
       "}\n",
       "iframe.fileview {\n",
       "  border: 0 none;\n",
       "  height: 100%;\n",
       "  width: 100%;\n",
       "  white-space: pre-wrap;\n",
       "}\n",
       ".pane-header-title {\n",
       "  width: 80%;\n",
       "  font-weight: 500;\n",
       "}\n",
       ".pane-header {\n",
       "  line-height: 1;\n",
       "  background-color: #4EC64B;\n",
       "  padding: 3px;\n",
       "}\n",
       ".pane-header .close {\n",
       "  font-size: 20px;\n",
       "  font-weight: 700;\n",
       "  float: right;\n",
       "  margin-top: -5px;\n",
       "}\n",
       ".master-wrapper .right-pane {\n",
       "  border: 1px inset silver;\n",
       "  width: 40%;\n",
       "  min-height: 300px;\n",
       "  flex: 3\n",
       "  min-width: 500px;\n",
       "}\n",
       ".master-wrapper * {\n",
       "  box-sizing: border-box;\n",
       "}\n",
       "</style><script>\n",
       "function copyToClipboard(fld) {\n",
       "    if (document.queryCommandSupported && document.queryCommandSupported('copy')) {\n",
       "        var textarea = document.createElement('textarea');\n",
       "        textarea.textContent = fld.innerHTML;\n",
       "        textarea.style.position = 'fixed';\n",
       "        document.body.appendChild(textarea);\n",
       "        textarea.select();\n",
       "\n",
       "        try {\n",
       "            return document.execCommand('copy'); // Security exception may be thrown by some browsers.\n",
       "        } catch (ex) {\n",
       "\n",
       "        } finally {\n",
       "            document.body.removeChild(textarea);\n",
       "        }\n",
       "    }\n",
       "}\n",
       "function expandPanel(el) {\n",
       "  const panelName = \"#\" + el.getAttribute('paneName');\n",
       "\n",
       "  // Get the base URL of the current notebook\n",
       "  var baseUrl = window.location.origin;\n",
       "\n",
       "  // Construct the full URL\n",
       "  var fullUrl = new URL(el.title, baseUrl).href;\n",
       "\n",
       "  document.querySelector(panelName + \"-title\").innerHTML = fullUrl\n",
       "  iframe = document.querySelector(panelName + \"-body\");\n",
       "\n",
       "  const tblcss = `<style> body { font-family: Arial, Helvetica, sans-serif;}\n",
       "    #csv { margin-bottom: 15px; }\n",
       "    #csv table { border-collapse: collapse;}\n",
       "    #csv table td { padding: 4px 8px; border: 1px solid silver;} </style>`;\n",
       "\n",
       "  function csvToHtmlTable(str) {\n",
       "    return '<div id=\"csv\"><table><tr><td>' +  str.replace(/[\\n\\r]+$/g, '').replace(/[\\n\\r]+/g, '</td></tr><tr><td>')\n",
       "      .replace(/,/g, '</td><td>') + '</td></tr></table></div>';\n",
       "  }\n",
       "\n",
       "  function reqListener () {\n",
       "    if (fullUrl.endsWith(\".csv\")) {\n",
       "      iframe.setAttribute(\"srcdoc\", tblcss + csvToHtmlTable(this.responseText));\n",
       "    } else {\n",
       "      iframe.setAttribute(\"srcdoc\", this.responseText);\n",
       "    }\n",
       "    console.log(this.responseText);\n",
       "  }\n",
       "\n",
       "  const oReq = new XMLHttpRequest();\n",
       "  oReq.addEventListener(\"load\", reqListener);\n",
       "  oReq.open(\"GET\", fullUrl);\n",
       "  oReq.send();\n",
       "\n",
       "\n",
       "  //iframe.src = fullUrl;\n",
       "  const resultPane = document.querySelector(panelName + \"-pane\");\n",
       "  if (resultPane.classList.contains(\"hidden\")) {\n",
       "    resultPane.classList.remove(\"hidden\");\n",
       "  }\n",
       "}\n",
       "function closePanel(el) {\n",
       "  const panelName = \"#\" + el.getAttribute('paneName')\n",
       "  const resultPane = document.querySelector(panelName + \"-pane\");\n",
       "  if (!resultPane.classList.contains(\"hidden\")) {\n",
       "    resultPane.classList.add(\"hidden\");\n",
       "  }\n",
       "}\n",
       "\n",
       "</script>\n",
       "<div class=\"master-wrapper\">\n",
       "  <div class=\"block master-tbl\"><div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th>project</th>\n",
       "      <th>uid</th>\n",
       "      <th>iter</th>\n",
       "      <th>start</th>\n",
       "      <th>end</th>\n",
       "      <th>state</th>\n",
       "      <th>kind</th>\n",
       "      <th>name</th>\n",
       "      <th>labels</th>\n",
       "      <th>inputs</th>\n",
       "      <th>parameters</th>\n",
       "      <th>results</th>\n",
       "      <th>artifact_uris</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>mlflow-tracking-example</td>\n",
       "      <td><div title=\"b45e8ffff4c34852b680d0a173b36297\"><a href=\"https://mlrun-ui.default-tenant.app.cust-cs-il.iguazio-cd0.com/mlprojects/mlflow-tracking-example/jobs/monitor-jobs/example-xgb-run-example-xgb-run/b45e8ffff4c34852b680d0a173b36297/overview\" target=\"_blank\" >...73b36297</a></div></td>\n",
       "      <td>0</td>\n",
       "      <td>Sep 11 16:51:38</td>\n",
       "      <td>NaT</td>\n",
       "      <td>completed</td>\n",
       "      <td>run</td>\n",
       "      <td>example-xgb-run-example-xgb-run</td>\n",
       "      <td><div class=\"dictlist\">v3io_user=xingsheng</div><div class=\"dictlist\">kind=local</div><div class=\"dictlist\">owner=xingsheng</div><div class=\"dictlist\">host=jupyter-xingsheng-7bff879869-b8jt8</div><div class=\"dictlist\">mlflow-user=iguazio</div><div class=\"dictlist\">mlflow-run-name=thoughtful-bird-981</div><div class=\"dictlist\">mlflow-run-id=b71f4f5507dd4ee1a60558b3c6e4cf4c</div><div class=\"dictlist\">mlflow-experiment-id=236670256527922352</div></td>\n",
       "      <td></td>\n",
       "      <td><div class=\"dictlist\">colsample_bytree=1.0</div><div class=\"dictlist\">custom_metric=None</div><div class=\"dictlist\">early_stopping_rounds=None</div><div class=\"dictlist\">eval_metric=mlogloss</div><div class=\"dictlist\">learning_rate=0.3</div><div class=\"dictlist\">maximize=None</div><div class=\"dictlist\">num_boost_round=10</div><div class=\"dictlist\">num_class=3</div><div class=\"dictlist\">objective=multi:softprob</div><div class=\"dictlist\">seed=42</div><div class=\"dictlist\">subsample=1.0</div><div class=\"dictlist\">verbose_eval=True</div></td>\n",
       "      <td><div class=\"dictlist\">accuracy=1.0</div><div class=\"dictlist\">log_loss=0.06621864238988215</div><div class=\"dictlist\">train-mlogloss=0.09053360810503364</div></td>\n",
       "      <td><div class=\"dictlist\">feature_importance_weight_json=store://artifacts/mlflow-tracking-example/example-xgb-run-example-xgb-run_feature_importance_weight_json#0@b45e8ffff4c34852b680d0a173b36297^39d4eeb702e17bd9458b72b86f61099f49591cb2</div><div class=\"dictlist\">feature_importance_weight_png=store://artifacts/mlflow-tracking-example/example-xgb-run-example-xgb-run_feature_importance_weight_png#0@b45e8ffff4c34852b680d0a173b36297^d16ab8817c0399762dbe4da03e0eec5636cdfdd2</div><div class=\"dictlist\">model=store://models/mlflow-tracking-example/example-xgb-run-example-xgb-run_model#0@b45e8ffff4c34852b680d0a173b36297^8bdd46de46f38f1e3c10ac5c34c421963e041341</div></td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div></div>\n",
       "  <div id=\"result1f836e5d-pane\" class=\"right-pane block hidden\">\n",
       "    <div class=\"pane-header\">\n",
       "      <span id=\"result1f836e5d-title\" class=\"pane-header-title\">Title</span>\n",
       "      <span onclick=\"closePanel(this)\" paneName=\"result1f836e5d\" class=\"close clickable\">&times;</span>\n",
       "    </div>\n",
       "    <iframe class=\"fileview\" id=\"result1f836e5d-body\"></iframe>\n",
       "  </div>\n",
       "</div>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<b> > to track results use the .show() or .logs() methods  or <a href=\"https://mlrun-ui.default-tenant.app.cust-cs-il.iguazio-cd0.com/mlprojects/mlflow-tracking-example/jobs/monitor-jobs/example-xgb-run-example-xgb-run/b45e8ffff4c34852b680d0a173b36297/overview\" target=\"_blank\">click here</a> to open in UI</b>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> 2025-09-11 16:52:02,061 [info] Run execution finished: {\"name\":\"example-xgb-run-example-xgb-run\",\"status\":\"completed\"}\n"
     ]
    }
   ],
   "source": [
    "# Run the example code using mlrun\n",
    "train_run = training_func.run(\n",
    "    local=True,\n",
    "    handler=\"example_xgb_run\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "655d5c46-2c0a-46f2-bbec-a58853260476",
   "metadata": {},
   "source": [
    "### Examine the results\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "d23beb02-e455-48dc-9d9f-9e3d4549ec71",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'accuracy': 1.0,\n",
       " 'log_loss': 0.06621864238988215,\n",
       " 'train-mlogloss': 0.09053360810503364,\n",
       " 'feature_importance_weight_json': 'store://artifacts/mlflow-tracking-example/example-xgb-run-example-xgb-run_feature_importance_weight_json:latest@b45e8ffff4c34852b680d0a173b36297^39d4eeb702e17bd9458b72b86f61099f49591cb2',\n",
       " 'feature_importance_weight_png': 'store://artifacts/mlflow-tracking-example/example-xgb-run-example-xgb-run_feature_importance_weight_png:latest@b45e8ffff4c34852b680d0a173b36297^d16ab8817c0399762dbe4da03e0eec5636cdfdd2',\n",
       " 'model': 'store://models/mlflow-tracking-example/example-xgb-run-example-xgb-run_model:latest@b45e8ffff4c34852b680d0a173b36297^8bdd46de46f38f1e3c10ac5c34c421963e041341'}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_run.outputs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "b05f4c2a-5f2d-4d7c-9c21-39c0a949cfc3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'accuracy': 1.0,\n",
       " 'log_loss': 0.06621864238988215,\n",
       " 'train-mlogloss': 0.09053360810503364}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "train_run.status.results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "925b3445-18b4-4497-9783-52b4cd069401",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "train_run.artifact(\"feature_importance_weight_png\").show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "227c4358-4c34-4d1c-acb4-e37ca110b8bf",
   "metadata": {},
   "source": [
    "### You can also examine the results using the UI"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dde00fd1-a1f0-4c56-80c2-c5d36a9062a1",
   "metadata": {},
   "source": [
    "Look at collected artifacts: "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8cda6c13-7fee-4284-aacf-81a506a426da",
   "metadata": {},
   "source": [
    "<img src=\"./_static/images/mlflow-artifacts.png\" width=\"1200\" >\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e1525230-e10c-4f48-b951-bc73642bb3e4",
   "metadata": {},
   "source": [
    "And at results:"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "217279f8-6af1-4209-b0ec-3d3d829ceed9",
   "metadata": {},
   "source": [
    "<img src=\"./_static/images/mlflow-results.png\" width=\"1200\" >"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "844edc05-0b6a-4e84-9213-1d3cbf6f833e",
   "metadata": {},
   "source": [
    "## Use the function for model serving"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af6489cb-35e2-4b0d-8a0d-e8954a44534a",
   "metadata": {},
   "source": [
    "### Implement the load and predict functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "381bb171-5111-4cc1-b81c-fdb813a6208f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting serving.py\n"
     ]
    }
   ],
   "source": [
    "%%writefile serving.py\n",
    "\n",
    "import zipfile\n",
    "from typing import Any, Dict, List, Union\n",
    "\n",
    "import mlflow\n",
    "import numpy as np\n",
    "import os\n",
    "import mlrun\n",
    "from mlrun.serving.v2_serving import V2ModelServer\n",
    "import xgboost as xgb\n",
    "import pandas as pd\n",
    "\n",
    "class MLFlowModelServer(V2ModelServer):\n",
    "    \"\"\"\n",
    "    The MLFlow tracker Model serving class  inherits the V2ModelServer class, resulting in automatic \n",
    "    initialization by the model server. It can run locally as part of a nuclio serverless function,\n",
    "    or as part of a real-time pipeline.\n",
    "    \"\"\"\n",
    "\n",
    "    def load(self):\n",
    "        \"\"\"\n",
    "        loads a model that was logged by the MLFlow tracker model\n",
    "        \"\"\"\n",
    "        # Unzip the model dir and then use mlflow's load function\n",
    "        model_file, _ = self.get_model(\".zip\")\n",
    "        model_path_unzip = model_file.replace(\".zip\", \"\")\n",
    "\n",
    "        with zipfile.ZipFile(model_file, \"r\") as zip_ref:\n",
    "            zip_ref.extractall(model_path_unzip)\n",
    "            \n",
    "        self.model = mlflow.pyfunc.load_model(model_path_unzip)\n",
    "\n",
    "    def predict(self, request: Dict[str, Any]) -> list:\n",
    "        \"\"\"\n",
    "        Infer the inputs through the model. The inferred data\n",
    "        is read from the \"inputs\" key of the request.\n",
    "\n",
    "        :param request: The request to the model using xgboost's predict. \n",
    "                The input to the model is read from the \"inputs\" key.\n",
    "\n",
    "        :return: The model's prediction on the given input.\n",
    "        \"\"\"\n",
    "        \n",
    "        # Get the inputs and set to accepted type:\n",
    "        inputs = pd.DataFrame(request[\"inputs\"])\n",
    "\n",
    "        # Predict using the model's predict function:\n",
    "        predictions = self.model.predict(inputs)\n",
    "\n",
    "        # Return as list:\n",
    "        return predictions.tolist()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "40182a6f-fc46-4a33-a7f5-7ee8ee171966",
   "metadata": {},
   "source": [
    "### Create the server and serving function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "f5fe910b-e177-4af7-84de-41a571d1774c",
   "metadata": {},
   "outputs": [],
   "source": [
    "serving_func = project.set_function(\n",
    "    func=\"serving.py\",\n",
    "    name=\"example-xgb-server\",\n",
    "    kind=\"serving\",\n",
    "    image=\"mlrun/mlrun\",\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "ddbfd48f-a90e-4fe6-9caa-ddffeacf63d1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<mlrun.serving.states.TaskStep at 0x7feae4c7da00>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Add the model\n",
    "serving_func.add_model(\n",
    "    \"mlflow_xgb_model\",\n",
    "    class_name=\"MLFlowModelServer\",\n",
    "    model_path=train_run.outputs[\"model\"],\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "2298d111-2f53-4b84-be9e-e4e8a228dcc4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "> 2025-09-11 16:52:02,757 [info] model mlflow_xgb_model was loaded\n",
      "> 2025-09-11 16:52:02,758 [info] Loaded ['mlflow_xgb_model']\n"
     ]
    }
   ],
   "source": [
    "# Create a mock server\n",
    "server = serving_func.to_mock_server()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f54d7c06-4972-4881-9bc9-fba7db0adbe4",
   "metadata": {},
   "source": [
    "### Test the model "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "4f256490-f225-4bd6-ac8a-5fc12a0f335d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# An example taken randomly from the dataset that the model was trained on, each\n",
    "x = [[5.1, 3.5, 1.4, 0.2]]\n",
    "result = server.test(\"/v2/models/mlflow_xgb_model/predict\", {\"inputs\": x})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "47839f4b-bb2d-4341-99c5-e34fa31270c9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'id': 'e0e53a970b89453f88ed1750f2e15900',\n",
       " 'model_name': 'mlflow_xgb_model',\n",
       " 'outputs': [[0.9505813121795654, 0.025876399129629135, 0.02354232780635357]],\n",
       " 'timestamp': '2025-09-11 16:52:02.763859+00:00'}"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Look at the result, it shows the probability of the given example to be each of the\n",
    "# irises featured in the dataset\n",
    "result"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "mlrun-base",
   "language": "python",
   "name": "conda-env-mlrun-base-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.18"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
